/*****************************************************
	smws8.h Dec 26, 2008 Joe Pardue
******************************************************/
// Prevent duplicate inclusion of this file
#ifndef SMWS8_H
#define SMWS8_H

#include <avr/io.h>
#include <avr/pgmspace.h> 
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>

void initialization(void);

// output string on both LCD and UART
void show(char s[]);


/*****************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************
	LCD SECTION
******************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************/

/************************************************************************/
// This is mostly lifted from the Buttefly sourcecode
// LCD_test.h
/************************************************************************/
void OnPUTF(char *PUTFstr);
void OnPUTS(char *pStr);
void OnPUTC(char *PUTCstr);
void OnCLEAR(void);
void OnCOLON(char *pOnoff);
void OnSETC(char *SETCstr);
void OnSCROLL(char *SCROLL);
/************************************************************************/
// This is mostly lifted from the Buttefly sourcecode
// LCD_driver.h
/************************************************************************/
//
//  Author(s)...: ATMEL Norway
//
//  Target(s)...: ATmega169
//
//  mt - used for debugging only - may not work

/************************************************************************/
// Definitions
/************************************************************************/
#define LCD_INITIAL_CONTRAST    0x0F
#define LCD_TIMER_SEED		    3
#define LCD_FLASH_SEED          10
#define LCD_REGISTER_COUNT      20
#define TEXTBUFFER_SIZE         25

#define SCROLLMODE_ONCE         0x01
#define SCROLLMODE_LOOP         0x02
#define SCROLLMODE_WAVE         0x03

/************************************************************************/
//MACROS
/************************************************************************/
//active = [TRUE;FALSE]
#define LCD_SET_COLON(active) LCD_Data[8] = active

// DEVICE SPECIFIC!!! (ATmega169)
#define pLCDREG ((unsigned char *)(0xEC))

// DEVICE SPECIFIC!!! (ATmega169) First LCD segment register
#define LCD_CONTRAST_LEVEL(level) LCDCCR=(0x0F & level)


/************************************************************************/
// Global variables
/************************************************************************/
extern volatile char gLCD_Update_Required;
extern char LCD_Data[LCD_REGISTER_COUNT];
extern char gTextBuffer[TEXTBUFFER_SIZE];
extern volatile char gScrollMode;
extern char gFlashTimer;
extern char gColon;
extern volatile signed char gScroll;


/************************************************************************/
// Global functions
/************************************************************************/
void LCD_Init (void);
void LCD_WriteDigit(char input, char digit);
void LCD_AllSegments(char show);

/************************************************************************/
// This is mostly lifted from the Buttefly sourcecode
// LCD_functions.h
/************************************************************************/

//
//  Author(s)...: ATMEL Norway
//
//  Target(s)...: ATmega169
//
//  mt - used for debugging only - may not work
// 

//#include <avr/pgmspace.h>
//Functions
// mt void LCD_puts_f(char __flash *pFlashStr, char scrollmode);
void LCD_puts_f(const char *pFlashStr, char scrollmode);
void LCD_puts(char *pStr, char scrollmode);
void LCD_UpdateRequired(char update, char scrollmode);
//void LCD_putc(char digit, char character);
void LCD_putc(uint8_t digit, char character);
void LCD_Clear(void);
void LCD_Colon(char show);
void LCD_FlashReset(void);
void SetContrast(char input);

//
//  Author(s)...: ATMEL Norway
//
//  Target(s)...: ATmega169
//
//  mt - used for debugging only - may not work
// LCD_driver.h

/************************************************************************/
// Definitions
/************************************************************************/
#define LCD_INITIAL_CONTRAST    0x0F
#define LCD_TIMER_SEED		    3
#define LCD_FLASH_SEED          10
#define LCD_REGISTER_COUNT      20
#define TEXTBUFFER_SIZE         25

#define SCROLLMODE_ONCE         0x01
#define SCROLLMODE_LOOP         0x02
#define SCROLLMODE_WAVE         0x03

/************************************************************************/
//MACROS
/************************************************************************/
//active = [TRUE;FALSE]
#define LCD_SET_COLON(active) LCD_Data[8] = active

// DEVICE SPECIFIC!!! (ATmega169)
#define pLCDREG ((unsigned char *)(0xEC))

// DEVICE SPECIFIC!!! (ATmega169) First LCD segment register
#define LCD_CONTRAST_LEVEL(level) LCDCCR=(0x0F & level)


/************************************************************************/
// Global variables
/************************************************************************/
extern volatile char gLCD_Update_Required;
extern char LCD_Data[LCD_REGISTER_COUNT];
extern char gTextBuffer[TEXTBUFFER_SIZE];
extern volatile char gScrollMode;
extern char gFlashTimer;
extern char gColon;
extern volatile signed char gScroll;


/************************************************************************/
// Global functions
/************************************************************************/
void LCD_Init (void);
void LCD_WriteDigit(char input, char digit);
void LCD_AllSegments(char show);



/*****************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************
	USART SECTION
******************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************/

uint16_t usartPutByte(uint8_t b, FILE *stream);

uint8_t isByteAvailable(void);
uint8_t receiveByte(void);
void sendbyte(uint8_t data);

uint8_t uartCount;
char uartString[64];
uint8_t checkUART(void);

/*****************************************************
	Select the AVR type you are using
		Remove '//' from device you are using
		Add '//' to devices you are not using
******************************************************/
//#define ATmega644
//#define ATmega32
//#define ATmega168
#define Butterfly

/*****************************************************
	Some of this is from Mike Perks, a generous AVRFreak
	- modified quite a bit

	These definitions allow us to use the code with 
	various AVRs and the Butterfly. They also make
	the cryptic register names a bit more readable
******************************************************/
/* defines for the various USART registers */
#if defined(ATmega32) || defined(Butterfly)

   // ATMega with one USART 
   #define USART_BAUD_RATE_LOW        	UBRRL
   #define USART_CONTROL_STATUS_REG_A	UCSRA
   #define USART_CONTROL_STATUS_REG_B	UCSRB
   #define USART_CONTROL_STATUS_REG_C	UCSRC
   #define USART_ENABLE_TRANSMITTER		TXEN
   #define USART_ENABLE_RECEIVER		RXEN
   #define USART_READY_TO_TRANSMIT		UDRE
   #define USART_TRANSMIT_COMPLETE		TXC
   #define USART_RECEIVE_COMPLETE		RXC
   #define USART_DATA_REG				UDR
   #define USART_STOP_BIT_SELECT 		USBS
   #define USART_CHARACTER_SIZE_0 		UCSZ0
   #define USART_CHARACTER_SIZE_1 		UCSZ1
   #define USART_REGISTER_SELECT		URSEL

#elif defined(ATmega168) || defined(ATmega644)

   // ATMega with two USARTs - USART 0
   #define USART_BAUD_RATE_LOW			UBRR0L
   #define USART_CONTROL_STATUS_REG_A	UCSR0A
   #define USART_CONTROL_STATUS_REG_B	UCSR0B
   #define USART_CONTROL_STATUS_REG_C	UCSR0C
   #define USART_ENABLE_TRANSMITTER		TXEN0
   #define USART_ENABLE_RECEIVER		RXEN0
   #define USART_READY_TO_TRANSMIT		UDRE0
   #define USART_TRANSMIT_COMPLETE		TXC0
   #define USART_RECEIVE_COMPLETE		RXC0
   #define USART_DATA_REG				UDR0
   #define USART_STOP_BIT_SELECT		USBS0
   #define USART_CHARACTER_SIZE			UCSZ00

#else
   #error "no USART definition for MCU"
#endif

/*****************************************************
	USART function declarations	 
******************************************************/
int usartPutChar(char c, FILE *stream);
void USARTInit();
void sendByte( uint8_t );
uint8_t receiveByte( void );
void sendPString(const char *); 

#if defined(Butterfly)
void OSCCAL_calibration(void);
void Delay(unsigned int) ;
#endif

#define sendUartFlashString(value) printf_P(PSTR(value))
#define sendUartRAMString(value) printf(value)

// output string on both LCD and UART
/*void show(char s[])
{
	//#define sendUartFlashString(value) printf_P(PSTR(value))
	printf_P(PSTR(s));
}*/

#define show(value) { printf_P(PSTR(value)); LCD_puts_f(PSTR(value), 1); }

/*****************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************
	PRINTF SECTION
******************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************/
void smPrintfInit(void);



/*****************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************
	JOYSTICK SECTION
******************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************/
#define TRUE 1
#define FALSE 0

// return 0 if no joy, anything else if joy
uint8_t checkJoystick(void);

volatile char joystickInput;
volatile char joystickChanged;

// declare global variables
volatile char joystickKey;
volatile char joystickKeyValid;

#define KEY_UP      0
#define KEY_DOWN    1
#define KEY_LEFT    2
#define KEY_RIGHT   3
#define KEY_PUSH    4
#define KEY_INVALID 5

#define BUTTON_A    6   // UP
#define BUTTON_B    7   // DOWN
#define BUTTON_C    2   // LEFT
#define BUTTON_D    3   // RIGHT
#define BUTTON_O    4   // PUSH

// declare functions
void pinChangeInterrupt(void);
char getkey(void);

void initializer(void);
void parseInput(char *);
void joystick(void);


/*****************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************
	MENU SECTION
******************************************************
>>>>>>>>>>>>>>>>>>>>>>>>>O<<<<<<<<<<<<<<<<<<<<<<<<<<<<
******************************************************/

// Dumping all the Workshop 6 stuff here for WS8
void parseUartInput(void);
void parseJoystickInput(void);

void state00(void);
void state01(void);
void state02(void);
void state03(void);
void state04(void);
void state05(void);
void state06(void);
void state07(void);
void state08(void);
void state09(void);
void state10(void);
void state11(void);
void state12(void);
void state13(void);
void state14(void);
void state15(void);
void state16(void);
void state17(void);

void menuState00Func(void);
void menuState01Func(void);
void menuState02Func(void);
void menuState03Func(void);
void menuState04Func(void);
void menuState05Func(void);
void menuState06Func(void);
void menuState07Func(void);
void menuState08Func(void);
void menuState09Func(void);
void menuState10Func(void);
void menuState11Func(void);
void menuState12Func(void);
void menuState13Func(void);
void menuState14Func(void);
void menuState15Func(void);
void menuState16Func(void);
void menuState17Func(void);

//const char LCD_START_msg[] PROGMEM = "LCD demo\0";

volatile uint8_t menuState;
volatile uint8_t keyPush;




#endif 
